package com.yangchuang.openpicture.util;


import com.yangchuang.openpicture.constant.JwtTokenClaimsConstants;
import com.yangchuang.openpicture.property.JwtProperties;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT 工具类
 */
@Component
public class JwtUtil {

    private final JwtProperties jwtProperties;

    public JwtUtil(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    /**
     * 根据配置的 secret 生成 SecretKey
     * @return SecretKey
     */
    private SecretKey getSecretKey() {
        return Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes(StandardCharsets.UTF_8));
    }


    public String createAccessToken(String userId, Integer role) {
        Map<String, String> claims = new HashMap<>();
        claims.put(JwtTokenClaimsConstants.USER_ID,userId);
        claims.put(JwtTokenClaimsConstants.USER_ROLE, String.valueOf(role));
        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + jwtProperties.getAccessTokenExpiration()))
                .signWith(getSecretKey(), SignatureAlgorithm.HS256)
                .compact();
    }

    /**
     * 创建 RefreshToken
     *
     * @param userid  主题（通常是用户ID）
     * @return RefreshToken 字符串
     */
    public String createRefreshToken(String userid) {
        // RefreshToken 通常只包含 subject 和过期时间，不携带额外的业务数据 (claims)
        return Jwts.builder()
                .setSubject(userid)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + jwtProperties.getRefreshTokenExpiration()))
                .signWith(getSecretKey(), SignatureAlgorithm.HS256)
                .compact();
    }

    /**
     * 解析 Token
     *
     * @param token JWT Token
     * @return Claims JWT 的载荷信息
     * @throws JwtException 如果 Token 无效（过期、签名错误等）
     */
    public Claims parseToken(String token) throws JwtException {
        return Jwts.parserBuilder()
                .setSigningKey(getSecretKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }


    /**
     * 获取Token剩余有效时间（毫秒）
     *
     * @param token JWT Token
     * @return 剩余有效时间，如果已过期返回0
     */
    public long getTokenRemainingTime(String token) {
        try {
            Claims claims = parseToken(token);
            Date expiration = claims.getExpiration();
            long remaining = expiration.getTime() - System.currentTimeMillis();
            return Math.max(remaining, 0);
        } catch (JwtException e) {
            return 0;
        }
    }
}